package com.wkbb.basic.utils.jvt;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wkbb.common.utils.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.net.URL;

/**
 * @author Alger Yang
 * @date 2019/9/24 002410:34
 */
@Slf4j
public class JvtBoxUtil {

    /**
     * P2P服务地址
     */
    private static final String URL = "http://47.102.43.117:8011/Request";

    /**
     * 获取设备信息
     */
    private static final String REQUEST_GET_DEVICE_INFO = "deviceInfoRequest";
    /**
     * NTP时间同步
     */
    private static final String REQUEST_TIME_SYNCHRONIZATION = "timeSynchronizationRequest";
    /**
     * 上传参数设置
     */
    private static final String REQUEST_SET_HTTP_PARAMETERS = "setHTTPParametersRequest";
    /**
     * 上传参数获取
     */
    private static final String REQUEST_GET_HTTP_PARAMETERS = "getHTTPParametersRequest";
    /**
     * 人员信息管理
     */
    private static final String REQUEST_PERSON_LIST = "personListRequest";
    /**
     * 获取人员名单
     */
    private static final String ACTION_GET_PERSON_LIST = "getPersonList";
    /**
     * 获取人员信息
     */
    private static final String ACTION_GET_PERSON = "getPerson";
    /**
     * 添加人员信息
     */
    public static final String ACTION_ADD_PERSON = "addPerson";
    /**
     * 删除人员名单
     */
    public static final String ACTION_DELETE_PERSON_LIST = "deletePersonList";
    /**
     * 删除人员信息
     */
    public static final String ACTION_DELETE_PERSON = "deletePerson";

    public static final int TYPE_BLACK_LIST = 1;
    public static final int TYPE_WHITE_LIST = 2;
    public static final int TYPE_VIP = 3;

    /**
     * 图片大小限制
     */
    private static final int IMG_LIMIT = 2;
    /**
     * 图片过大错误码
     */
    public static final Integer CODE_ERROR_IMG_SIZE = 10086;

    /**
     * 为请求添加鉴权信息
     *
     * @param uuid       设备UUID
     * @param jvtRequest 巨龙请求
     */
    private static void signRequest(String uuid, JvtBoxBean jvtRequest) {
        jvtRequest.setTimeStamp(System.currentTimeMillis() / 1000);
        jvtRequest.setUuid(uuid);
        jvtRequest.setSession(uuid);
        jvtRequest.setSign("");
    }

    /**
     * 向巨龙P2P服务发送网络请求
     *
     * @param uuid       设备UUID
     * @param jvtRequest 巨龙请求
     * @return 巨龙P2P服务响应结果
     */
    private static JvtBoxBean doRequest(String uuid, JvtBoxBean jvtRequest) {
        signRequest(uuid, jvtRequest);

        String json = JSON.toJSONString(jvtRequest);
        log.info(json);

        String result = HttpClientUtil.doPostJson(URL, json);
        if (result == null) {
            return null;
        }

        return JSON.parseObject(result, JvtBoxBean.class);
    }

    /**
     * 向巨龙P2P服务发送网络请求
     *
     * @param jvtRequest 巨龙请求
     * @return 巨龙P2P服务响应结果
     */
    private static JvtBoxBean doRequest(JvtBoxBean jvtRequest) {
        String json = JSON.toJSONString(jvtRequest);
        logRequest(jvtRequest);
        String str = HttpClientUtil.doPostJson(URL, json);
        if (str == null) {
            return null;
        }

        JvtBoxBean result = JSON.parseObject(str, JvtBoxBean.class);
        log.info("【巨龙】盒子响应请求" + str);
        logErrorMsg(result == null ? 0 : result.getCode());
        return result;
    }

    private static void logRequest(JvtBoxBean jvtRequest) {
        jvtRequest.clearPersonPhoto();
        log.info("【巨龙】向盒子发送请求,{}", JSON.toJSONString(jvtRequest));
    }

    public static JvtBoxBean getDeviceInfo(String uuid) {
        JvtBoxBean jvtRequest = new JvtBoxBean();
        jvtRequest.setName(REQUEST_GET_DEVICE_INFO);

        return doRequest(uuid, jvtRequest);
    }

    public static JvtBoxBean syncTime(String uuid) {
        JvtBoxBean jvtRequest = new JvtBoxBean();
        jvtRequest.setName(REQUEST_TIME_SYNCHRONIZATION);

        return doRequest(uuid, jvtRequest);
    }

    public static JvtBoxBean setParams(String uuid, JvtBoxConfig jvtBoxConfig) {
        JvtBoxBean jvtRequest = new JvtBoxBean();
        jvtRequest.setName(REQUEST_SET_HTTP_PARAMETERS);
        jvtRequest.setData(JSON.parseObject(JSON.toJSONString(jvtBoxConfig)));

        return doRequest(uuid, jvtRequest);
    }

    public static JvtBoxBean getParams(String uuid) {
        JvtBoxBean jvtRequest = new JvtBoxBean();
        jvtRequest.setName(REQUEST_GET_HTTP_PARAMETERS);

        return doRequest(uuid, jvtRequest);
    }

    public static JvtBoxBean getPersonList(String uuid, int personType) {
        return managePersonList(uuid, ACTION_GET_PERSON_LIST, personType, new JSONObject());
    }

    public static JvtBoxBean getPerson(String uuid, int personType, String personId, boolean getPhoto) {
        JSONObject data = new JSONObject();
        data.put("PersonId", personId);
        data.put("GetPhoto", getPhoto ? 1 : 0);

        return managePersonList(uuid, ACTION_GET_PERSON, personType, data);
    }

    public static JvtBoxBean addPerson(String uuid, int personType, String personId, String image) {
        JSONObject data = new JSONObject();
        JSONObject personInfo = new JSONObject();
        personInfo.put("PersonId", personId);
        personInfo.put("PersonPhoto", image);
        //下面这三个暂时用不上但是对于巨龙p2p服务是必填项
        personInfo.put("PersonName", personId);
        personInfo.put("Phone", "");
        personInfo.put("Birthday", "");
        data.put("PersonInfo", personInfo);

        return managePersonList(uuid, ACTION_ADD_PERSON, personType, data);
    }

    public static JvtBoxBean deletePerson(String uuid, int personType, String personId) {
        JSONObject data = new JSONObject();
        data.put("PersonId", personId);

        return managePersonList(uuid, ACTION_DELETE_PERSON, personType, data);
    }

    public static JvtBoxBean deletePersonList(String uuid, int personType) {
        return managePersonList(uuid, ACTION_DELETE_PERSON_LIST, personType, new JSONObject());
    }

    private static JvtBoxBean getJvtRequest(String action, int personType, JSONObject data) {
        data.put("Action", action);
        data.put("PersonType", personType);

        JvtBoxBean jvtRequest = new JvtBoxBean();
        jvtRequest.setName(REQUEST_PERSON_LIST);
        //Session和UUID一致
        jvtRequest.setData(data);
        return jvtRequest;
    }

    public static JvtBoxBean managePersonList(String uuid, String action, int personType, JSONObject data) {
        JvtBoxBean jvtRequest = getJvtRequest(action, personType, data);

        return doRequest(uuid, jvtRequest);
    }

    /**
     * 获取添加人员任务信息
     *
     * @param uuid       设备UUID
     * @param personType 人员类型
     * @param personId   人员PersonId
     * @param faceUrl    人脸图片地址
     * @return 任务信息
     */
    public static JvtBoxBean getAddPersonTask(String uuid, Integer personType, String personId, String faceUrl) {
        JSONObject data = new JSONObject();
        JSONObject personInfo = new JSONObject();
        personInfo.put("PersonId", personId);
        //下面这三个暂时用不上但是对于巨龙p2p服务是必填项
        personInfo.put("PersonName", personId);
        personInfo.put("Phone", "");
        personInfo.put("Birthday", "");
        data.put("PersonInfo", personInfo);

        JvtBoxBean jvtRequest = getJvtRequest(ACTION_ADD_PERSON, personType, data);
        signRequest(uuid, jvtRequest);
        //队列用参数
        jvtRequest.setFaceUrl(faceUrl);
        jvtRequest.setAction(ACTION_ADD_PERSON);
        return jvtRequest;
    }

    /**
     * 获取删除人员任务信息
     *
     * @param uuid       设备UUID
     * @param personType 人员类型
     * @return 任务信息
     */
    public static JvtBoxBean getDeletePersonTask(String uuid, Integer personType, String personId) {
        JSONObject data = new JSONObject();
        data.put("PersonId", personId);
        JvtBoxBean jvtRequest = getJvtRequest(ACTION_DELETE_PERSON, personType, data);
        signRequest(uuid, jvtRequest);
        //队列用参数
        jvtRequest.setAction(ACTION_DELETE_PERSON);
        return jvtRequest;
    }

    /**
     * 获取删除人员列表任务信息
     *
     * @param uuid       设备UUID
     * @param personType 人员类型
     * @return 任务信息
     */
    public static JvtBoxBean getDeletePersonListTask(String uuid, Integer personType) {
        JvtBoxBean jvtRequest = getJvtRequest(ACTION_DELETE_PERSON_LIST, personType, new JSONObject());
        signRequest(uuid, jvtRequest);
        //队列用参数
        jvtRequest.setAction(ACTION_DELETE_PERSON_LIST);
        return jvtRequest;
    }

    /**
     * 执行任务
     *
     * @param task 巨龙任务
     */
    public static JvtBoxBean execTask(JvtBoxBean task) throws Exception {
        Integer personType = task.getData().getInteger("PersonType");
        JSONObject personInfo = task.getData().getJSONObject("PersonInfo");
        String personId = null;
        if (personInfo != null) {
            personId = personInfo.getString("PersonId");
        }
        if (ACTION_ADD_PERSON.equals(task.getAction())) {
            //巨龙设备无法处理转义字符
            if (personInfo != null) {
                //若图片大小大于2M，不处理
                byte[] data = JvtBase64Util.url2Data(new URL(task.getFaceUrl()));
                float mb = data.length / 1024f / 1024;
                if (mb > IMG_LIMIT) {
                    task.setCode(CODE_ERROR_IMG_SIZE);
                    task.setMessage("图片大小:" + mb + "MB,大于" + IMG_LIMIT + "MB,personId:" + personId + "," + task.getFaceUrl());
                    log.warn("【巨龙】图片大小:" + mb + "MB,大于" + IMG_LIMIT + "MB,personId:" + personId + "," + task.getFaceUrl());
                    return task;
                }
                personInfo.put("PersonPhoto", JvtBase64Util.data2Base64(data).replace("\r", "").replace("\n", ""));
            }
        }

        JvtBoxBean result = doRequest(task);
        logResult(task, personId, personType, result);
        return result;
    }

    private static void logResult(JvtBoxBean task, String personId, Integer personType, JvtBoxBean result) {
        switch (task.getAction()) {
            case ACTION_ADD_PERSON:
                if (result == null || result.getCode() != 1) {
                    log.warn("【巨龙】添加人员失败 UUID:{},personId:{},personType:{},result:{}", task.getUuid(), personId, personType, result);
                } else {
                    log.info("【巨龙】添加人员成功 UUID:{},personId:{},personType:{}", task.getUuid(), personId, personType);
                }
                break;
            case ACTION_DELETE_PERSON:
                if (result == null || result.getCode() != 1) {
                    log.warn("【巨龙】删除人员失败 UUID:{},personId:{},personType:{},result:{}", task.getUuid(), personId, personType, result);
                } else {
                    log.info("【巨龙】删除人员成功 UUID:{},personId:{},personType:{}", task.getUuid(), personId, personType);
                }
                break;
            case ACTION_DELETE_PERSON_LIST:
                if (result == null || result.getCode() != 1) {
                    log.warn("【巨龙】删除人员名单失败 UUID:{},personType:{},result:{}", task.getUuid(), personType, result);
                } else {
                    log.info("【巨龙】删除人员名单成功 UUID:{},personType:{}", task.getUuid(), personType);
                }
                break;
            default:
                break;
        }
    }

    private static void logErrorMsg(int code) {
        String msg = "【巨龙】code = " + code + " ";
        switch (code) {
            case 1:
                msg += "成功";
                break;
            case -1:
                msg += "参数错误";
                break;
            case -2:
                msg += "参数配置错误";
                break;
            case -3:
                msg += "检脸错误";
                break;
            case -4:
                msg += "获取特征值失败";
                break;
            case -5:
                msg += "比对失败";
                break;
            case -6:
                msg += "网络连接失败";
                break;
            case -7:
                msg += "线程失败";
                break;
            case -8:
                msg += "设备已经存在";
                break;
            case -9:
                msg += "设备总数错误";
                break;
            case -10:
                msg += "malloc失败";
                break;
            case -11:
                msg += "无空闲设备";
                break;
            case -12:
                msg += "设备不存在";
                break;
            case -13:
                msg += "设备初始化错误";
                break;
            case -14:
                msg += "服务没有初始化";
                break;
            case -15:
                msg += "创建socket失败";
                break;
            case -16:
                msg += "接受scoket失败";
                break;
            case -17:
                msg += "select 失败";
                break;
            case -18:
                msg += "发送失败";
                break;
            case -19:
                msg += "接收失败";
                break;
            case -20:
                msg += "转化jpeg失败";
                break;
            case -21:
                msg += "内部命令错误";
                break;
            case -22:
                msg += "数据库ID";
                break;
            case -23:
                msg += "数据库满";
                break;
            case -24:
                msg += "数据库未知错误";
                break;
            case -25:
                msg += "名单不存在";
                break;
            case -26:
                msg += "图片文件大小错误";
                break;
            case -27:
                msg += "图片文件格式错误";
                break;
            case -28:
                msg += "图片名字格式错误";
                break;
            case -29:
                msg += "这个设备的流已经存在";
                break;
            default:
                msg += "失败";
        }
        if (code == 1) {
            log.info(msg);
        } else {
            log.warn(msg);
        }
    }
}
